﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace OOLib
{
   /// <summary>
   /// Provides a collection of implementations for services.
   /// </summary>
   /// <remarks>
   /// This is a singleton you commonly find in your component context under key /singletons/com.sun.star.lang.theServiceManager.
   /// The factories are accessed with a service name. It is possible to access the factories with their implementation names, 
   /// but you should avoid this.
   /// </remarks>
   public class ServiceManager : Component, IMultiServiceFactory
   {
      /// <summary>
      /// Gets the singelton instance of the ServiceManager
      /// </summary>
      public static ServiceManager Instance { get; private set; }

      /// <summary>
      /// Constructor
      /// </summary>
      public ServiceManager() :
         base()
      {
         if (Instance != null)
         {
            throw new InvalidOperationException(
               "Only one instance of ServiceManager can be created. Use the static property instance to access it.");
         }
         ComObj = System.Activator.CreateInstance(Type.GetTypeFromProgID("com.sun.star.ServiceManager"));
         _MultiServiceFactoryImpl = new MultiServiceFactoryImpl(this);
         Instance = this;
      }

      #region IMultiServiceFactory

      private MultiServiceFactoryImpl _MultiServiceFactoryImpl;

      /// <summary>
      /// Creates an instance classified by the specified name. 
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance </param>
      /// <returns>Return a new instance.</returns>
      public object CreateInstance(string serviceSpecifier)
      {
         return _MultiServiceFactoryImpl.CreateInstance(serviceSpecifier);
      }

      /// <summary>
      /// Creates an instance classified by the specified name and passes the arguments to that instance.
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance</param>
      /// <param name="arguments">Arguments passed to the instance</param>
      /// <returns>Return a new instance.</returns>
      public object CreateInstanceWithArguments(string serviceSpecifier, object[] arguments)
      {
         return _MultiServiceFactoryImpl.CreateInstanceWithArguments(serviceSpecifier, arguments);
      }

      /// <summary>
      /// Provides the available names of the factory to be used to create instances.
      /// </summary>
      /// <returns>Returns a sequence of all names.</returns>
      public string[] GetAvailableServiceNames()
      {
         return _MultiServiceFactoryImpl.GetAvailableServiceNames();
      }

      #endregion

      #region properties

      /// <summary>
      /// Gets the default component context to be used, if instanciating services via MultiServiceFactory.
      /// </summary>
      public ComponentContext DefaultContext
      {
         get
         {
            CheckDisposed();
            return GetObjectWrapper<ComponentContext>(GetProperty("DefaultContext"));
         }
      }

      #endregion

      #region utility methods

      /// <summary>
      /// Creates a new Desktop object.
      /// </summary>
      /// <returns>Returns a new instance of Desktop.</returns>
      public Desktop CreateDesktop()
      {
         CheckDisposed();
         return new Desktop(CreateInstance("com.sun.star.frame.Desktop"));
      }

      private CoreReflection _CoreReflection = null;

      /// <summary>
      /// Gets a CoreReflection object.
      /// </summary>
      public CoreReflection CoreReflection
      {
         get
         {
            CheckDisposed();
            if (_CoreReflection == null)
            {
               _CoreReflection = new CoreReflection(CreateInstance("com.sun.star.reflection.CoreReflection"));
            }
            return _CoreReflection;
         }
      }

      #endregion
   }
}
